package m.appserver;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import m.system.db.DBConfig;
import m.system.listener.InitListener;
import m.system.task.SystemTask;
import m.system.util.SystemUtil;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class WebServer {
	/**
	 * 开启服务  需配置端口
	 */
	public static void start(int port) throws Exception {
		start(port,1024,100*1024*1024);
	}
	/**
	 * 开启服务  需配置端口 列队数
	 */
	public static void start(int port,int backlog) throws Exception {
		start(port,backlog,100*1024*1024);
	}
	/**
	 * 开启服务  需配置端口 列队数 最大内容长度
	 */
	public static void start(int port,int backlog,int maxContentLength) throws Exception {
		runServer(port,backlog,maxContentLength);
	}
	public static void stop() {
		InitListener.destroyed();//停止主机服务
		if(null!=future){
			for(ChannelHandlerContext ctx : channelMap.values()){
				try {
					ctx.close().sync();
				} catch (InterruptedException ignored) { }
			}
			channelMap=new HashMap<>();
			future.addListener(ChannelFutureListener.CLOSE);
			future=null;
		}
	}
	private static ChannelFuture future=null;
	protected static Map<String,ChannelHandlerContext> channelMap=new HashMap<>();
	
	private static void runServer(int port,int backlog,int maxContentLength) throws Exception {
		long t=new Date().getTime();
		EventLoopGroup boss = new NioEventLoopGroup(1);
		int max=DBConfig.getMaxConnect();
		max=max>1000?max-500:max/2;
		EventLoopGroup worker = new NioEventLoopGroup(max);
		try {
			ServerBootstrap bootstrap = new ServerBootstrap();
			bootstrap.group(boss,worker)
					// 指定存放请求的队列的长度
					.option(ChannelOption.SO_BACKLOG, backlog)
					// 指定是否启用心跳机制来检测长连接的存活性，即客户端的存活性
					//.childOption(ChannelOption.SO_KEEPALIVE, true)
					//指定channel类型
					.channel(NioServerSocketChannel.class)
					//初始化channel管道
					.childHandler(new ChannelInitializer<SocketChannel>() {
						@Override
						protected void initChannel(SocketChannel ch) {
							ChannelPipeline pipeline = ch.pipeline();
							pipeline.addLast("decoder", new HttpRequestDecoder());
							pipeline.addLast("encoder", new HttpResponseEncoder());
							pipeline.addLast("aggregator", new HttpObjectAggregator(maxContentLength));
							pipeline.addLast(new ServerHandler());
						}
					});
			//监听端口8888启动Server
			future = bootstrap.bind(port).sync();
			SystemUtil.printlnIf(true,"appServer启动成功(",new Date().getTime()-t,"ms)，port：",port);
			SystemTask.setLogPrint();
			future.channel().closeFuture().sync();
		} finally {
			boss.shutdownGracefully();
			worker.shutdownGracefully();
			SystemUtil.printlnIf(true,"-----WebServer关闭-----");
			stop();
		}
	}
}
